package it.graph;

import static java.lang.Math.*;

import java.text.DecimalFormat;
import java.util.Locale;

public class InfoMaps {
	
	/*
	 * 
	 * 		Metodo per calcolare i margini della mappa data la latitudine
	 * 		e la longitudine
	 * 
	 * 		Ref: https://github.com/tuupola/php_google_maps
	 * 
	 * 		static offset = 268435456;
	 * 		static raggio = 85445659.44705395;
	 * 		static radConv = PIGRECO/180;
	 * 		static gradConv = 180/PIGRECO;
	 * 
	 * 		dimX = dimX*scale;
	 * 		dimY = dimY*scale;
	 * 
	 * 		funzione LongToX(l) {return round(offset+raggio*l*radConv);}
	 * 		funzione LatToY(l) {return round(offset-raggio*log((1+sin(l*radConv))/(1-sin(l*radConv)))/2);}
	 * 		funzione XToLong(x) {return ((round(x)-offset)/raggio)*radConv;}
	 * 		funzione YToLat(y) {return (PIGRECO/2-2*atan(exp((round(y)-offset)/raggio)))*gradConv;}
	 * 
	 * 
	 * 		deltaX = round(dimX/2);
	 * 		deltaY = round(dimY/2);
	 * 
	 * 		funzione regolaLongConPixel(l,d,z) {return XToLong(LongToX(l)+(d<<(21-z)));}
	 * 		funzione regolaLatConPixel(l,d,z) {return YToLat(LatToY(l)+(d<<(21-z)));}
	 * 
	 * 		lat
	 * 		long
	 * 		zoom
	 * 		
	 * 		Richiamare queste funzioni
	 * 		confineNord = InfoMaps.regolaLatConPixel(lat,-deltaY,zoom);
	 * 		confineSud = InfoMaps.regolaLatConPixel(lat,deltaY,zoom);
	 * 		confineOvest = InfoMaps.regolaLongConPixel(long,-deltaX,zoom);
	 * 		confineEst = InfoMaps.regolaLongConPixel(long,deltaX,zoom);
	 * 
	 */
	
	private static final long offset = 268435456;
	private static final Double raggio = 85445659.44705395;
	private static final Double radConv = PI/180;
	private static final Double gradConv = 180/PI;	
	private static final Double raggioTerrestre = 6371.005;
	
	private static DecimalFormat df6;
	private static DecimalFormat df3;
	
	static {
		
		df6 = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
		df3 = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
		df6.applyPattern("##.######");
		df3.applyPattern("##.###");
		
		
	}
	
	static long LongToX(Double lng) {
		return round(offset+raggio*lng*radConv);
	}
	
	static long LatToY(Double lat) {
		return round(offset-raggio*log((1+sin(lat*radConv))/(1-sin(lat*radConv)))/2);
	}
	
	static Double XToLong(long x) {
		return ((round(x)-offset)/raggio)*gradConv;
	}
	
	static Double YToLat(long y) {
		return (PI/2-2*atan(exp((round(y)-offset)/raggio)))*gradConv;
	}
	
	static Double regolaLongConPixel(Double lng, int delta, int zoom, int px) {
		return XToLong(LongToX(lng)+((delta + px)<<(21-zoom)));
	}
	
	static Double regolaLatConPixel(Double lat, int delta, int zoom, int px) {
		return YToLat(LatToY(lat)+((delta + px)<<(21-zoom)));
	}
	
	static String format6(Double num) {
		return df6.format(num);
	}
	
	static String format3(Double num) {
		return df3.format(num);
	}
	
	public static Double calcolaDistanzaKM(ConvPoint alfa, ConvPoint beta){
		Double angoloAB = abs((alfa.getLng() - beta.getLng())*radConv);		
		Double res =  raggioTerrestre * 
				(
						acos(
								sin(beta.getLat()*radConv)
								*sin(alfa.getLat()*radConv)
								+
								cos(beta.getLat()*radConv)
								*cos(alfa.getLat()*radConv)
								*cos(angoloAB)
							)
					) ;
	
		return res;
	}
	
}
